package comment

import (
	"community-service/cmd/api/internal/models/model"
	"community-service/cmd/api/internal/svc"
	"community-service/cmd/api/internal/types"
	e "community-service/pkg/errorx"
	"context"
	"fmt"
	user "gitee.com/vzerx/proto-contracts/auth"
	"google.golang.org/grpc/codes"

	"github.com/zeromicro/go-zero/core/logx"
)

type UserListPostCommentLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewUserListPostCommentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserListPostCommentLogic {
	return &UserListPostCommentLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// getTopLevelCommentIds 获取分页的顶级评论ID列表
func (l *UserListPostCommentLogic) getTopLevelCommentIds(postId int64, pageNum, pageSize int) ([]int64, int64, error) {
	var commentIds []int64
	var total int64

	// 查询顶级评论总数
	if err := l.svcCtx.DB.WithContext(l.ctx).Model(&model.CsCommunityPostComment{}).
		Where("post_id = ? AND pid IS NULL", postId).
		Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询顶级评论ID
	if err := l.svcCtx.DB.WithContext(l.ctx).Model(&model.CsCommunityPostComment{}).
		Select("id").
		Where("post_id = ? AND pid IS NULL", postId).
		Order("is_topped DESC, created_at ASC").
		Limit(pageSize).
		Offset((pageNum - 1) * pageSize).
		Find(&commentIds).Error; err != nil {
		return nil, 0, err
	}

	return commentIds, total, nil
}

// getAllCommentsByTopLevelIds 使用CTE递归查询顶级评论及其所有子评论
func (l *UserListPostCommentLogic) getAllCommentsByTopLevelIds(topLevelIds []int64, userId int64) ([]*types.PostCommentRsp, error) {
	if len(topLevelIds) == 0 {
		return []*types.PostCommentRsp{}, nil
	}

	var allComments []*types.PostCommentRsp

	// 构建占位符
	placeholders := ""
	args := make([]interface{}, 0, len(topLevelIds)+1)
	for i, id := range topLevelIds {
		if i > 0 {
			placeholders += ","
		}
		placeholders += "?"
		args = append(args, id)
	}
	args = append(args, userId)

	// 使用递归CTE查询所有相关评论
	sql := fmt.Sprintf(`
		WITH RECURSIVE comment_tree AS (
			-- 起始条件：选择分页的顶级评论
			SELECT id FROM %s WHERE id IN (%s)
			UNION ALL
			-- 递归条件：查找子评论
			SELECT c.id FROM %s c
			INNER JOIN comment_tree ct ON c.pid = ct.id
		)
		SELECT 
			comment.id, comment.post_id, comment.pid, comment.content, comment.is_topped,
			comment.create_user, comment.create_username, comment.reply_user, comment.reply_username,
			UNIX_TIMESTAMP(comment.created_at) AS created_at,
			UNIX_TIMESTAMP(comment.updated_at) AS updated_at,
			IFNULL(COUNT(DISTINCT approve_map.id), 0) AS approve_count,
			CASE WHEN is_approved.id IS NOT NULL THEN 1 ELSE 0 END AS is_approved,
			CASE WHEN comment.create_user = ? THEN 1 ELSE 0 END AS owner
		FROM comment_tree ct
		INNER JOIN %s comment ON comment.id = ct.id
		LEFT JOIN %s approve_map ON approve_map.comment_id = comment.id
		LEFT JOIN %s is_approved ON is_approved.comment_id = comment.id AND is_approved.create_user = ?
		GROUP BY comment.id
		ORDER BY comment.is_topped DESC, comment.created_at ASC`,
		model.TableNameCsCommunityPostComment,
		placeholders,
		model.TableNameCsCommunityPostComment,
		model.TableNameCsCommunityPostComment,
		model.TableNameCsCommunityPostCommentApprove,
		model.TableNameCsCommunityPostCommentApprove,
	)

	// 添加用户ID参数（用于is_approved查询）
	args = append(args, userId)

	if err := l.svcCtx.DB.WithContext(l.ctx).Raw(sql, args...).Scan(&allComments).Error; err != nil {
		return nil, err
	}

	return allComments, nil
}

func (l *UserListPostCommentLogic) UserListPostComment(req *types.UserPostCommentReq) (*types.UserPostCommentList, error) {

	// 检查帖子是否存在
	var existPost model.CsCommunityPost
	if err := l.svcCtx.DB.WithContext(l.ctx).Model(&model.CsCommunityPost{}).
		Where("id = ?", req.Id).Find(&existPost).Error; err != nil {
		return nil, e.NewGrpcErr(codes.Internal, e.DBError)
	}

	if existPost.ID == 0 {
		return nil, e.NewGrpcErr(codes.NotFound, e.CommentPostNotFound)
	}

	// 第一步：分页查询顶级评论ID
	topLevelIds, total, err := l.getTopLevelCommentIds(req.Id, req.PageNum, req.PageSize)
	if err != nil {
		return nil, e.NewGrpcErr(codes.Internal, e.DBError)
	}

	// 如果没有顶级评论，直接返回空结果
	if len(topLevelIds) == 0 {
		return &types.UserPostCommentList{}, nil
	}

	// 第二步：使用CTE递归查询所有相关评论（包括子评论）
	allComments, err := l.getAllCommentsByTopLevelIds(topLevelIds, req.UserProfile.UserId)
	if err != nil {
		return nil, e.NewGrpcErr(codes.Internal, e.DBError)
	}

	// 第三步：批量查询用户信息
	userIDs := make(map[int64]bool)
	for _, comment := range allComments {
		userIDs[comment.CreateUser] = true
		if comment.ReplyUser != 0 {
			userIDs[comment.ReplyUser] = true
		}
	}

	userInfoMap := make(map[int64]*types.AuthorRsp)
	for userID := range userIDs {
		if userInfo, err := l.svcCtx.User.GetUserInfo(l.ctx, &user.UserInfoReq{
			UserId: userID,
		}); err == nil && userInfo != nil {
			userInfoMap[userID] = &types.AuthorRsp{
				Id:            userInfo.UserId,
				Name:          userInfo.UserName,
				Sex:           userInfo.Sex,
				Avatar:        userInfo.Avatar,
				CollageName:   userInfo.CollageName,
				SecondOrgName: userInfo.SecOrgName,
				OrgName:       userInfo.OrgName,
			}
		}
	}

	// 第四步：填充用户信息
	for _, comment := range allComments {
		if authorInfo, exists := userInfoMap[comment.CreateUser]; exists {
			comment.Author = authorInfo
		} else {
			comment.Author = &types.AuthorRsp{
				Id:   comment.CreateUser,
				Name: comment.CreateUsername,
			}
		}

		if comment.ReplyUser > 0 {
			if replyUserInfo, exists := userInfoMap[comment.ReplyUser]; exists {
				comment.ReplyUsername = replyUserInfo.Name
			}
		}
	}

	// 第五步：构建树形结构
	commentMap := make(map[int64]*types.PostCommentRsp)
	var topLevelComments []*types.PostCommentRsp

	// 建立所有评论的映射
	for _, comment := range allComments {
		comment.Children = []*types.PostCommentRsp{} // 初始化子评论数组
		commentMap[comment.Id] = comment
	}

	// 建立父子关系，只保留分页查询到的顶级评论
	topLevelIdSet := make(map[int64]bool)
	for _, id := range topLevelIds {
		topLevelIdSet[id] = true
	}

	for _, comment := range allComments {

		if comment.Pid == 0 && topLevelIdSet[comment.Id] {
			// 分页范围内的顶级评论
			topLevelComments = append(topLevelComments, comment)
		} else if comment.Pid != 0 {
			// 子评论，找到父评论并添加到其children中
			if parent, exists := commentMap[comment.Pid]; exists {
				parent.Children = append(parent.Children, comment)
			}
		}
	}

	return &types.UserPostCommentList{
		Data:  topLevelComments,
		Total: total,
	}, nil
}
